#include "gui.h"
#include "ssd1306.h"
//#include "stdlib.h"
#include "string.h"
#include "stdio.h"
#include "i2c.h"

static char key_state_str[4][10] = {"CLEAR", "SINGLE", "DOUBLE", "LONG"};
static char key_name_str[5][10] = {"NO", "ENCODER", "LEFT", "MIDDLE", "RIGHT"};
static char run_state_str[3][10] = {"RUN", "STOP", "WAIT"};
static char trig_mode_str[3][10] = {"AUTO", "NORMAL", "SINGLE"};

void gui_test_input(int16_t encoder_cnt, uint8_t encoder_dir, KeyInfo key_info) {
    static char str[100];

    ssd1306_Fill(Black);

    ssd1306_SetCursor(0, 0);
    sprintf(str, "enc_cnt: %d", encoder_cnt);
    ssd1306_WriteString(str, Font_7x10, White);

    ssd1306_SetCursor(0, 10);
    sprintf(str, "enc_dir: %d", encoder_dir);
    ssd1306_WriteString(str, Font_7x10, White);

    ssd1306_SetCursor(0, 20);
    sprintf(str, "key_state: %s", key_state_str[key_info.state]);
    ssd1306_WriteString(str, Font_7x10, White);

    ssd1306_SetCursor(0, 30);
    sprintf(str, "key_name: %s", key_name_str[key_info.name]);
    ssd1306_WriteString(str, Font_7x10, White);

    ssd1306_UpdateScreen(&hi2c1);
}

void gui_draw_grid() {
    // Horizontal lines
    for (int i = 0; i < 64; i += 10)
        for (int j = 0; j < 128; j += 3)
            ssd1306_DrawPixel(j, 63 - i, White);
    // Vertical lines
    for (int i = 0; i < 128; i += 10)
        for (int j = 0; j < 64; j += 3)
            ssd1306_DrawPixel(i, j, White);
}

/**
 * @brief 主界面GUI
 * @param points 波形的点
 * @param num 波形点的数量
 * @param run_state 运行状态
 * @param trig_mode 触发状态
 * @param ver 垂直偏转系数
 * @param hor 水平偏转系数
 */
void
gui_main_interface(uint16_t *points, uint16_t num, uint8_t run_state, uint8_t trig_mode, uint16_t ver, uint16_t hor,
                   uint16_t trig_level, uint16_t trig_level_mV, SelectOption option) {
    static char str[100];

    ssd1306_Fill(Black);

    // Grid
    gui_draw_grid();

    // Waveform
    for (uint16_t i = 1; i < 128; i++) {
        if (points[i - 1] < points[i]) {
            for (int j = points[i - 1]; j <= points[i]; j++) {
                ssd1306_DrawPixel(i, 63 - j, White);
            }
        } else {
            for (int j = points[i - 1]; j >= points[i]; j--) {
                ssd1306_DrawPixel(i, 63 - j, White);
            }
        }
    }

    // Trig level
    ssd1306_SetCursor(92, 54);
    if (trig_level_mV >= 1000) {
        sprintf(str, "%.2fV", trig_level_mV / 1000.0);
    } else {
        sprintf(str, "%dmV", trig_level_mV);
    }
    if (option == OPT_TRIG_LEVEL) {
        for (int i = 0; i < 128; i += 2)
            ssd1306_DrawPixel(i, 63 - trig_level, White);
        ssd1306_WriteString(str, Font_7x10, Black);
    } else
        ssd1306_WriteString(str, Font_7x10, White);

    // Run state
    ssd1306_SetCursor(0, 0);
    if (option == OPT_RUN_STATE)
        ssd1306_WriteString((const char *) (run_state_str + run_state), Font_7x10, Black);
    else
        ssd1306_WriteString((const char *) (run_state_str + run_state), Font_7x10, White);

    // Trig mode
    ssd1306_SetCursor(85, 0);
    if (option == OPT_TRIG_MODE)
        ssd1306_WriteString((const char *) (trig_mode_str + trig_mode), Font_7x10, Black);
    else
        ssd1306_WriteString((const char *) (trig_mode_str + trig_mode), Font_7x10, White);

    // Vertical ratio
    ssd1306_SetCursor(0, 44);
    if (ver >= 1000) {
        sprintf(str, "%.1fV", ver / 1000.0);
    } else {
        sprintf(str, "%dmV", ver);
    }
    if (option == OPT_VER)
        ssd1306_WriteString(str, Font_7x10, Black);
    else
        ssd1306_WriteString(str, Font_7x10, White);

    // Horizontal ratio
    ssd1306_SetCursor(0, 54);
    sprintf(str, "%dus", hor);
    if (option == OPT_HOR)
        ssd1306_WriteString(str, Font_7x10, Black);
    else
        ssd1306_WriteString(str, Font_7x10, White);

    ssd1306_UpdateScreen(&hi2c1);
}

void gui_startup() {
    ssd1306_Fill(White);
    ssd1306_SetCursor(30, 10);
    ssd1306_WriteString("Simple", Font_11x18, Black);
    ssd1306_SetCursor(25, 30);
    ssd1306_WriteString("Oscillo", Font_11x18, Black);
    ssd1306_SetCursor(45, 48);
    ssd1306_WriteString("By.Mo", Font_7x10, Black);

    ssd1306_UpdateScreen(&hi2c1);
}

void gui_measure(uint16_t *points, uint16_t num, uint32_t period, uint32_t frequency, uint32_t V_max, uint32_t V_min,
                 uint32_t V_pp, double V_rms) {
    static char str[100];

    ssd1306_Fill(Black);

    // Grid
    gui_draw_grid();

    // Waveform
    for (uint16_t i = 1; i < 128; i++) {
        if (points[i - 1] < points[i]) {
            for (int j = points[i - 1]; j <= points[i]; j++) {
                ssd1306_DrawPixel(i, 63 - j, White);
            }
        } else {
            for (int j = points[i - 1]; j >= points[i]; j--) {
                ssd1306_DrawPixel(i, 63 - j, White);
            }
        }
    }

    // Period
    ssd1306_SetCursor(0, 0);
    if (period >= 1000)
        sprintf(str, "T:%.1fms", period / 1000.0);
    else
        sprintf(str, "T:%luus", period);
    ssd1306_WriteString(str, Font_7x10, White);

    // Frequency
    ssd1306_SetCursor(0, 10);
    if(frequency >= 1000000)
        sprintf(str, "f:%.2fMHz", frequency / 1000000.0);
    else if (frequency >= 1000)
        sprintf(str, "f:%.2fkHz", frequency / 1000.0);
    else
        sprintf(str, "f:%luHz", frequency);
    ssd1306_WriteString(str, Font_7x10, White);

    // Vmax
    ssd1306_SetCursor(0, 20);
    if(V_max >= 1000)
        sprintf(str, "Vmax:%.2fV", V_max / 1000.0);
    else
        sprintf(str, "Vmax:%lumV", V_max);
    ssd1306_WriteString(str, Font_7x10, White);

    // Vmin
    ssd1306_SetCursor(0, 30);
    if(V_min >= 1000)
        sprintf(str, "Vmin:%.2fV", V_min / 1000.0);
    else
        sprintf(str, "Vmin:%lumV", V_min);
    ssd1306_WriteString(str, Font_7x10, White);

    // Vpp
    ssd1306_SetCursor(0, 40);
    if(V_pp >= 1000)
        sprintf(str, "Vpp:%.2fV", V_pp / 1000.0);
    else
        sprintf(str, "Vpp:%lumV", V_pp);
    ssd1306_WriteString(str, Font_7x10, White);

    // Vrms
    ssd1306_SetCursor(0, 50);
    if(V_rms >= 1)
        sprintf(str, "Vrms:%.2fV", V_rms);
    else
        sprintf(str, "Vrms:%.0fmV", V_rms * 1000.0);
    ssd1306_WriteString(str, Font_7x10, White);

    ssd1306_UpdateScreen(&hi2c1);
}
